package com.ajavaer.framework.common.validate;

import com.ajavaer.framework.common.tools.AnnotationTools;
import com.ajavaer.framework.common.tools.ObjectTools;
import com.ajavaer.framework.common.tools.ReflectTools;
import com.ajavaer.framework.common.tools.StringTools;
import com.ajavaer.framework.common.validate.annotation.CheckField;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Map;

public class Validation {
    private static ThreadLocal<ScriptEngine> nashorn = new ThreadLocal();

    public static ValidationException error(String msg) {
        return new ValidationException(new ValidationResult(false, msg));
    }

    public static <T> ValidationResult assertSuccess(T t) {
        ValidationResult exec = exec(t);
        if (exec.isSuccess()) {
            return exec;
        }
        throw new ValidationException(exec);
    }

    public static <T> ValidationResult exec(T t) {
        ValidationResult result = new ValidationResult();
        if (t == null) {
            result.setSuccess(false);
            result.setMsg("待检查对象为null");
            return result;
        }
        String jjsScript = "";
        try {
            Map<Field, Annotation> annotationMap = AnnotationTools.findAllFieldAnnotation(t.getClass(), CheckField.class);
            boolean flag = true;
            for (Map.Entry<Field, Annotation> fieldEntry : annotationMap.entrySet()) {
                CheckField annotation = (CheckField) fieldEntry.getValue();
                Field field = fieldEntry.getKey();
                Object value = ReflectTools.getValue(field, t);
                jjsScript = annotation.expression();
                //表达式优先级最高
                if (StringTools.isNotBlank(jjsScript) && value != null) {
                    flag = checkExpression(jjsScript, t);
                    if (!flag) {
                        result.setMsg(annotation.message());
                        break;
                    }
                } else if (StringTools.isNotBlank(annotation.regex()) && value != null && value instanceof String) {//正则表达式
                    flag = StringTools.regexMatch(value.toString(), annotation.regex());
                    if (!flag) {
                        result.setMsg(annotation.message());
                        break;
                    }
                } else {
                    //为空判断
                    if (annotation.notEmpty() && ObjectTools.isBlank(value)) {
                        flag = false;
                        result.setMsg(annotation.message());
                        break;
                    }
                    //null判断
                    if (annotation.notNull() && value == null) {
                        flag = false;
                        result.setMsg(annotation.message());
                        break;
                    }
                    //数值判断
                    if (value != null && value instanceof Number) {
                        Number num = ((Number) value);
                        //小于
                        if (StringTools.isNotBlank(annotation.lt())) {
                            Double target = Double.valueOf(annotation.lt());
                            if (target <= num.doubleValue()) {
                                flag = false;
                                result.setMsg(annotation.message());
                                break;
                            }
                        }
                        //大于
                        if (StringTools.isNotBlank(annotation.gt())) {
                            Double target = Double.valueOf(annotation.gt());
                            if (target >= num.doubleValue()) {
                                flag = false;
                                result.setMsg(annotation.message());
                                break;
                            }
                        }
                        //小于等于
                        if (StringTools.isNotBlank(annotation.le())) {
                            Double target = Double.valueOf(annotation.le());
                            if (target < num.doubleValue()) {
                                flag = false;
                                result.setMsg(annotation.message());
                                break;
                            }
                        }
                        //大于等于
                        if (StringTools.isNotBlank(annotation.ge())) {
                            Double target = Double.valueOf(annotation.ge());
                            if (target > num.doubleValue()) {
                                flag = false;
                                result.setMsg(annotation.message());
                                break;
                            }
                        }
                    }
                    //长度
                    if (StringTools.isNotBlank(annotation.length()) && value != null && value instanceof String) {
                        String target = annotation.length();
                        if (target.contains("~") || target.contains(",") || target.contains("-")) {
                            String[] tar = target.split("~|,|-");
                            Integer min = Integer.valueOf(tar[0]);
                            Integer max = Integer.valueOf(tar[1]);
                            if (!(value.toString().length() >= min && value.toString().length() <= max)) {
                                flag = false;
                                result.setMsg(annotation.message());
                                break;
                            }
                        } else {
                            Integer max = Integer.valueOf(target);
                            if (value.toString().length() > max) {
                                flag = false;
                                result.setMsg(annotation.message());
                                break;
                            }
                        }
                    }
                }

            }
            result.setSuccess(flag);
        } catch (IllegalAccessException e) {
            result.setSuccess(false);
            result.setMsg("读取对象属性异常：" + e.getMessage());
        } catch (ScriptException e) {
            result.setSuccess(false);
            result.setMsg("验证表达式（" + jjsScript + "）不合法：" + e.getMessage());
        } catch (Exception e) {
            result.setSuccess(false);
            result.setMsg("验证表达式异常：" + e.getMessage());
        }
        return result;
    }

    public static <T> boolean checkExpression(String expression, T t) throws ScriptException {
        //把pojo对象传入脚本
        SimpleBindings binds = new SimpleBindings();
        binds.put("d", t);
        ScriptEngine engine = nashorn.get();
        if (engine == null) {
            engine = new ScriptEngineManager().getEngineByName("nashorn");
            nashorn.set(engine);
        }
        //执行表达式
        Object eval = engine.eval(expression, binds);
        boolean flag = true;
        if (eval instanceof Boolean) {
            flag = (Boolean) eval;
        } else if (eval instanceof String) {
            flag = StringTools.isNotBlank(eval.toString()) && !((String) eval).equalsIgnoreCase("false");
        }
        return flag;
    }
}
